循环引用问题:图示如下:其中我们可以发现,这两个对象存在了互相引用的关系,但如果我del掉这两个对象,这两个对象并不会释放内存,就会存在内存被无效占用的情况,这是十分可惜的 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hw02zJ4l-1640334304946)(python面向对象生命周期.assets/1640331091300.png)] import objgraph
# 这里是一个新加入的包,包通过setting中的project 中的第一选项,中的➕进行添加
# objgraph.count("类名") 可以查看,垃圾回收机制中对象的引用次数 跟踪对象的个数
# 内存管理机制 = 引用计算器机制 + 垃圾回收机制
垃圾回收机制 # 主要作用:从经历过“引用计数器机制”依然未被释放的对象中,找到“循环引用”,干掉相关对象
# 底层机制(了解):
# 1.收集所有的“容器对象”(可以引用其他对象的对象,基础类型不算),通过一个双向链表进行引用
# 2.针对每一个“容器对象”,通过一个变量gc_refs来记录当前对应的引用计数
# 3.对于每个“容器对象”,找到它引用的“容器对象”,并将这个“容器对象”的引用计数 -1
# 4.经过步骤3之后,如果一个“容器对象”的引用计数为0,就代表可以被回收了,肯定是“循环引用”
# 但如果每次都把所有对象检查一边,就会很浪费性能,所以python采用了一个名为“分代回收”机制(思想)
# 1.首先默认一个对象被创建出来以后,属于0代
# 2.如果经历这一代“垃圾回收”后,依然存活,则划分到下一代
# 3.“垃圾回收”的周期顺序为:0代”垃圾回收“达到一定次数,会触发 0代和1代回收 1代"垃圾回收"达到一定次数,会触发0代,1代和2代回收
# 再垃圾回收器中,新增的对象个数- 消亡的对象个数,达到一定的阈值时,才会触发垃圾检测
# 查看和设置相关参数
import gc
print(gc.get_threshold())
gc.set_threshold(70,10,5) # 相差700时开始检测,10 5 触发一代和二代
# 自动回收
# 1.开启垃圾回收机制
gc.enable() # 开启垃圾回收机制(默认开启)
gc.disable() # 关闭垃圾回收机制
gc.isenabled() # 判定是否开启
# 手动回收:
import gc
gc.collect() # 运行回收垃圾
# 阈值:
gc.get_threshold() # 获取自动自动回收阈值
gc.set_threshold() # 设置自动回收阈值
# 版本兼容问题:
# python 3.x版本如上
# python 2.x版本:一旦有一个对象实现了del方法,系统便不会自动帮我们释放
# 解决方案1:尽量避免循环应用
# 解决方案2:采用软引用(即计算器不会加1),例如:
import weakref
import
p.pet = d # d的引用次数为2,但删除p以后,d会减一
gc.set_threshold(70,10,5)
p.pet = {"dog":weakref(d1),"cat":weakref(c1)}
# 当像上面那样引用对象较多时,可以采用字典
# weakref。WeakValueDictionary({"dog": d1,"cat": c1})
|